package ua.kiev.ntukpi.asu.ga.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.nio.channels.SelectableChannel;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.table.DefaultTableModel;

import ua.kiev.ntukpi.asu.ga.CustomAlgorithm;
import ua.kiev.ntukpi.asu.ga.Individual;
import ua.kiev.ntukpi.asu.ga.Job;
import ua.kiev.ntukpi.asu.ga.PopulationGenerator;
import ua.kiev.ntukpi.asu.ga.Utils;
import ua.kiev.ntukpi.asu.ga.impl.CanonicalAligorithm;
import ua.kiev.ntukpi.asu.ga.impl.CrossoverOneDot;
import ua.kiev.ntukpi.asu.ga.impl.FitnessImpl;
import ua.kiev.ntukpi.asu.ga.impl.MutationPlain;
import ua.kiev.ntukpi.asu.ga.impl.RemoverWorst;
import ua.kiev.ntukpi.asu.ga.impl.SelectionBest;
import ua.kiev.ntukpi.asu.ga.interfaces.Algorithm;
import ua.kiev.ntukpi.asu.ga.interfaces.Crossover;
import ua.kiev.ntukpi.asu.ga.interfaces.Fitness;
import ua.kiev.ntukpi.asu.ga.interfaces.Method;
import ua.kiev.ntukpi.asu.ga.interfaces.Mutation;
import ua.kiev.ntukpi.asu.ga.interfaces.Remover;
import ua.kiev.ntukpi.asu.ga.interfaces.Selection;


/**
 *
 * @author  Alexander Galibey
 */
public class MainFrame extends javax.swing.JFrame {
	
	private static final int DEFAULT_WIDTH = 400;
	
	private static final int DEFAULT_HEIGHT = 400;
	
	private static int RADIUS = 10;
	
	private PairsHolder paintHolder = new PairsHolder();
	
	private Algorithm algorithm = new CanonicalAligorithm();
	
	private boolean isStopped;
	
	private List<Individual> population = new ArrayList<Individual>();
	
	private PopulationGUIUpdater updater = new PopulationGUIUpdater(this);
	
	private Individual bestIndividual;
	
	private Individual worstIndividual;
	
	private Dimension screenSize;
	
	private DefaultTableModel tableModel = new DefaultTableModel();
	
	private DefaultTableModel showIndModel = new DefaultTableModel();
	
	private List<Method> availableSelections = new ArrayList<Method>();
	
	private List<Method> availableMutations = new ArrayList<Method>();
	
	private List<Method> availableRemovers = new ArrayList<Method>();
	
	private List<Method> availableCrossovers = new ArrayList<Method>();
	
	private Runnable alghorithmThread = new Runnable(){
		
		public void run() {

			while(!isStopped){
				
				getAlgorithm().nextGeneration(population);
				updater.update(population);
				
			}
		}
	};
	
	private Runnable statusThread = new Runnable(){

		public void run() {

			while (!isStopped) {
				List<Individual> sorted = new ArrayList<Individual>(population);
				Collections.sort(sorted, getFitness().getComparator());
				setWorstIndividual(sorted.get(0));
				setBestIndividual(sorted.get(sorted.size() - 1));
				updateStatus();
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
		
	};

	private javax.swing.JDialog autoGenerate;
    private javax.swing.JDialog creatingDialog;
    private javax.swing.JButton showCreatingBtn;
    private javax.swing.JButton jButton10;
    private javax.swing.JButton jButton11;
    private javax.swing.JButton jButton12;
    private javax.swing.JButton addJobButton;
    private javax.swing.JButton deleteJobButton;
    private javax.swing.JButton manuallyOkButton;
    private javax.swing.JButton manuallyCancelButton;
    private javax.swing.JButton jButton17;
    private javax.swing.JButton runButton;
    private javax.swing.JButton stopButton;
    private javax.swing.JButton showIndBest;
    private javax.swing.JButton showIndWorst;
    private javax.swing.JButton showSettingBtn;
    private javax.swing.JButton saveSettingBtn;
    private javax.swing.JButton jButton8;
    private javax.swing.JButton jButton9;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JList removerList;
    private javax.swing.JList selectionList;
    private javax.swing.JList mutationList;
    private javax.swing.JList crossoverList;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JScrollPane jScrollPane6;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JTable jTable1;
    private javax.swing.JTable jTable2;
    private javax.swing.JTextField bestTextField;
    private javax.swing.JTextField entireDeadlineText;
    private javax.swing.JTextField populationCountText;
    private javax.swing.JTextField worstTextField;
    private javax.swing.JTextField crossoverFactor;
    private javax.swing.JTextField jobsCountText;
    private javax.swing.JTextField indCountText;
    private javax.swing.JTextField durationText;
    private javax.swing.JTextField deadlineText;
    private javax.swing.JTextField deleteNumberText;
    private javax.swing.JTextField fitnessText;
    private JDialog manuallyGenerate;
    private JDialog settingDialog;
    private JDialog showDialog;

	private JDialog messageDialog;

	private JLabel jLabel17;

	private JButton jButton18;

	private Fitness fitness = new FitnessImpl();
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/** Creates new form TempFrame */
    public MainFrame() {
        initComponents();
        locateCenter(this);
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">                          
    private void initComponents() {
        
    	screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    	tableModel.setColumnIdentifiers(new String[]{"Number", "Duration", "Deadline"});
    	showIndModel.setColumnIdentifiers(new String[]{"Number", "Duration", "Deadline"});
    	availableSelections.add(new SelectionBest(getFitness()));
    	availableRemovers.add(new RemoverWorst(getFitness()));
    	availableMutations.add(new MutationPlain());
    	availableCrossovers.add(new CrossoverOneDot());
    	settingDialog = new JDialog();
        jLabel4 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        removerList = new javax.swing.JList();
        jLabel5 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        selectionList = new javax.swing.JList();
        crossoverFactor = new javax.swing.JTextField();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        mutationList = new javax.swing.JList();
        jLabel8 = new javax.swing.JLabel();
        jScrollPane4 = new javax.swing.JScrollPane();
        crossoverList = new javax.swing.JList();
        saveSettingBtn = new javax.swing.JButton();
        jButton8 = new javax.swing.JButton();
        jButton9 = new javax.swing.JButton();
        creatingDialog = new JDialog();
        jButton10 = new javax.swing.JButton();
        jButton11 = new javax.swing.JButton();
        autoGenerate = new JDialog();
        jLabel9 = new javax.swing.JLabel();
        jobsCountText = new javax.swing.JTextField();
        jLabel10 = new javax.swing.JLabel();
        indCountText = new javax.swing.JTextField();
        jButton12 = new javax.swing.JButton();
        manuallyGenerate = new JDialog();
        jScrollPane5 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jLabel11 = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        durationText = new javax.swing.JTextField();
        deadlineText = new javax.swing.JTextField();
        addJobButton = new javax.swing.JButton();
        jLabel13 = new javax.swing.JLabel();
        deleteNumberText = new javax.swing.JTextField();
        deleteJobButton = new javax.swing.JButton();
        manuallyOkButton = new javax.swing.JButton();
        manuallyCancelButton = new javax.swing.JButton();
        jLabel16 = new javax.swing.JLabel();
        populationCountText = new javax.swing.JTextField();
        showDialog = new JDialog();
        jScrollPane6 = new javax.swing.JScrollPane();
        jTable2 = new javax.swing.JTable();
        jLabel14 = new javax.swing.JLabel();
        fitnessText = new javax.swing.JTextField();
        jLabel15 = new javax.swing.JLabel();
        entireDeadlineText = new javax.swing.JTextField();
        jButton17 = new javax.swing.JButton();
        messageDialog = new javax.swing.JDialog();
        jLabel17 = new javax.swing.JLabel();
        jButton18 = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel(){
        	
        	protected void paintComponent(Graphics g) {
        	
        		super.paintComponent(g);
        		drawCircles((Graphics2D)g);
        	}
        };
        showCreatingBtn = new javax.swing.JButton();
        runButton = new javax.swing.JButton();
        stopButton = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JSeparator();
        jLabel1 = new javax.swing.JLabel();
        bestTextField = new javax.swing.JTextField();
        showIndBest = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        worstTextField = new javax.swing.JTextField();
        showIndWorst = new javax.swing.JButton();
        showSettingBtn = new javax.swing.JButton();

        settingDialog.getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        settingDialog.setModal(true);
        settingDialog.setResizable(false);
        settingDialog.setSize(450, 350);
        locateCenter(settingDialog);
        jLabel4.setText("Selection:");
        settingDialog.getContentPane().add(jLabel4, new org.netbeans.lib.awtextra.AbsoluteConstraints(20, 20, -1, -1));

        removerList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = getNames(availableRemovers);
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        removerList.setSelectedIndex(0);
        jScrollPane1.setViewportView(removerList);

        settingDialog.getContentPane().add(jScrollPane1, new org.netbeans.lib.awtextra.AbsoluteConstraints(180, 160, 110, 80));

        jLabel5.setText("Crossover:");
        settingDialog.getContentPane().add(jLabel5, new org.netbeans.lib.awtextra.AbsoluteConstraints(20, 140, -1, -1));

        selectionList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = getNames(availableSelections);
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        selectionList.setSelectedIndex(0);
        jScrollPane2.setViewportView(selectionList);

        settingDialog.getContentPane().add(jScrollPane2, new org.netbeans.lib.awtextra.AbsoluteConstraints(20, 40, 120, 80));

        settingDialog.getContentPane().add(crossoverFactor, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 270, 30, -1));
        crossoverFactor.setText("0.3");
        jLabel6.setText("Crossover factor:");
        settingDialog.getContentPane().add(jLabel6, new org.netbeans.lib.awtextra.AbsoluteConstraints(20, 270, -1, -1));

        jLabel7.setText("Mutation:");
        settingDialog.getContentPane().add(jLabel7, new org.netbeans.lib.awtextra.AbsoluteConstraints(180, 20, -1, -1));

        mutationList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = getNames(availableMutations);
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        mutationList.setSelectedIndex(0);
        jScrollPane3.setViewportView(mutationList);

        settingDialog.getContentPane().add(jScrollPane3, new org.netbeans.lib.awtextra.AbsoluteConstraints(180, 40, 110, 80));

        jLabel8.setText("Remover:");
        settingDialog.getContentPane().add(jLabel8, new org.netbeans.lib.awtextra.AbsoluteConstraints(180, 140, -1, -1));

        crossoverList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = getNames(availableCrossovers);
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        crossoverList.setSelectedIndex(0);
        jScrollPane4.setViewportView(crossoverList);

        settingDialog.getContentPane().add(jScrollPane4, new org.netbeans.lib.awtextra.AbsoluteConstraints(20, 160, 120, 80));

        saveSettingBtn.setText("Save");
        saveSettingBtn.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                
            	int selectionIndex = selectionList.getSelectedIndex();
            	int crossIndex = crossoverList.getSelectedIndex();
            	int mutationIndex = mutationList.getSelectedIndex();
            	int removerIndex = removerList.getSelectedIndex();
            	
            	final double factor = Double.parseDouble(crossoverFactor.getText());
            	
            	CustomAlgorithm customAlgorithm = new CustomAlgorithm(){

					
					public void nextGeneration(List<Individual> population) {
						
						List<Individual> parents = getSelection().select(population);
						List<Individual> childs = getCrossover().cross(parents, factor);
						getMutation().mutate(childs, factor);
						population.addAll(childs);
						getRemover().remove(population, parents, childs);
					}
            		
            	};
            	customAlgorithm.setSelection((Selection)availableSelections.get(selectionIndex));
            	customAlgorithm.setCrossover((Crossover)availableCrossovers.get(crossIndex));
            	customAlgorithm.setMutation((Mutation)availableMutations.get(mutationIndex));
            	customAlgorithm.setRemover((Remover)availableRemovers.get(removerIndex));
            	customAlgorithm.setFitness(getFitness());
            	algorithm = customAlgorithm;
            	settingDialog.setVisible(false);
            }
        });

        settingDialog.getContentPane().add(saveSettingBtn, new org.netbeans.lib.awtextra.AbsoluteConstraints(320, 90, 90, -1));

        jButton8.setText("Cancel");
        jButton8.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton8MouseClicked(evt);
            }
        });

        settingDialog.getContentPane().add(jButton8, new org.netbeans.lib.awtextra.AbsoluteConstraints(320, 140, 90, -1));

        jButton9.setText("Default");
        settingDialog.getContentPane().add(jButton9, new org.netbeans.lib.awtextra.AbsoluteConstraints(320, 190, 90, -1));

        creatingDialog.getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        creatingDialog.setModal(true);
        creatingDialog.setResizable(false);
        creatingDialog.setSize(400, 80);
        locateCenter(creatingDialog);
        jButton10.setText("Generate Automatically");
        jButton10.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton10ActionPerformed(evt);
            }
        });
        jButton10.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton10MouseClicked(evt);
            }
        });

        creatingDialog.getContentPane().add(jButton10, new org.netbeans.lib.awtextra.AbsoluteConstraints(30, 10, -1, -1));

        jButton11.setText("Put manually");
        jButton11.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton11ActionPerformed(evt);
            }
        });
        jButton11.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton11MouseClicked(evt);
            }
        });

        creatingDialog.getContentPane().add(jButton11, new org.netbeans.lib.awtextra.AbsoluteConstraints(223, 10, 140, -1));

        autoGenerate.setModal(true);
        autoGenerate.setResizable(false);
        autoGenerate.setSize(400, 110);
        locateCenter(autoGenerate);
        jLabel9.setText("Jobs amount:");

        jLabel10.setText("Population count:");

        jButton12.setText("Generate");
        jButton12.addMouseListener(new MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                
                 int jobsCount = Integer.parseInt(jobsCountText.getText());
                 int populationSize = Integer.parseInt(indCountText.getText());
                 population = PopulationGenerator.generate(jobsCount, populationSize);
                 updater.update(population);
                 runButton.setEnabled(true);
                 autoGenerate.setVisible(false);
                 creatingDialog.setVisible(false);
            }
        });

        jobsCountText.setText("20");
        indCountText.setText("200");
        org.jdesktop.layout.GroupLayout autoGenerateLayout = new org.jdesktop.layout.GroupLayout(autoGenerate.getContentPane());
        autoGenerate.getContentPane().setLayout(autoGenerateLayout);
        autoGenerateLayout.setHorizontalGroup(
            autoGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(autoGenerateLayout.createSequentialGroup()
                .add(25, 25, 25)
                .add(jLabel9)
                .add(13, 13, 13)
                .add(jobsCountText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 31, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(34, 34, 34)
                .add(jLabel10)
                .add(4, 4, 4)
                .add(indCountText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 33, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(31, Short.MAX_VALUE))
            .add(org.jdesktop.layout.GroupLayout.TRAILING, autoGenerateLayout.createSequentialGroup()
                .addContainerGap(124, Short.MAX_VALUE)
                .add(jButton12)
                .add(119, 119, 119))
        );
        autoGenerateLayout.setVerticalGroup(
            autoGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(autoGenerateLayout.createSequentialGroup()
                .add(21, 21, 21)
                .add(autoGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel9)
                    .add(jobsCountText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel10)
                    .add(indCountText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 12, Short.MAX_VALUE)
                .add(jButton12)
                .addContainerGap())
        );
        manuallyGenerate.setModal(true);
        manuallyGenerate.setResizable(false);
        manuallyGenerate.setSize(550, 500);
        locateCenter(manuallyGenerate);
        jTable1.setModel(tableModel);
        jScrollPane5.setViewportView(jTable1);

        jLabel11.setText("Duration:");

        jLabel12.setText("Deadline:");

        addJobButton.setText("Add");
        addJobButton.addMouseListener(new MouseAdapter(){
        	
        	public void mouseClicked(MouseEvent e) {

        		int count = tableModel.getRowCount() + 1;
        		String duration = durationText.getText();
        		String deadline = deadlineText.getText();
        		tableModel.addRow(new Object[]{count, duration, deadline});
        	}
        });

        jLabel13.setText("Number:");

        deleteJobButton.setText("Delete");
        deleteJobButton.addMouseListener(new MouseAdapter(){
        	
        	public void mouseClicked(MouseEvent e) {

        		int deleteIndex = Integer.parseInt(deleteNumberText.getText());
        		tableModel.removeRow(deleteIndex - 1);
        		for (int i = 0; i < tableModel.getRowCount(); i++){
        			
        			tableModel.setValueAt(i + 1, i, 0);
        		}
        	}
        });

        manuallyOkButton.setText("OK");
        manuallyOkButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                
            	
            	List<Job> jobs = new ArrayList<Job>();
            	for (int i = 0; i < tableModel.getRowCount(); i++){
            		
            		jobs.add(new Job(i + 1, Integer.parseInt(tableModel
							.getValueAt(i, 1)
							+ ""), Integer.parseInt(tableModel.getValueAt(i, 2)
							+ "")));
				}
            	population = PopulationGenerator.generate(jobs, Integer.parseInt(populationCountText.getText()));
            	updater.update(population);
            	List<Individual> sorted = new ArrayList<Individual>(population);
				Collections.sort(sorted, getFitness().getComparator());
				setWorstIndividual(sorted.get(0));
				setBestIndividual(sorted.get(sorted.size() - 1));
				
            	updateStatus();
            	manuallyGenerate.setVisible(false);
                creatingDialog.setVisible(false);
                runButton.setEnabled(true);
            }
        });

        manuallyCancelButton.setText("Cancel");
        manuallyCancelButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                
            	manuallyGenerate.setVisible(false);
                creatingDialog.setVisible(false);
            }
        });

        jLabel16.setText("Population count:");
        populationCountText.setText("100");
        org.jdesktop.layout.GroupLayout manuallyGenerateLayout = new org.jdesktop.layout.GroupLayout(manuallyGenerate.getContentPane());
        manuallyGenerate.getContentPane().setLayout(manuallyGenerateLayout);
        manuallyGenerateLayout.setHorizontalGroup(
            manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(manuallyGenerateLayout.createSequentialGroup()
                .addContainerGap()
                .add(jScrollPane5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 270, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(manuallyGenerateLayout.createSequentialGroup()
                        .add(14, 14, 14)
                        .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(manuallyGenerateLayout.createSequentialGroup()
                                .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                                    .add(durationText, 0, 0, Short.MAX_VALUE)
                                    .add(jLabel11, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .add(deleteNumberText)
                                    .add(jLabel16))
                                .add(19, 19, 19)
                                .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(manuallyGenerateLayout.createSequentialGroup()
                                        .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                                            .add(deadlineText, 0, 0, Short.MAX_VALUE)
                                            .add(jLabel12, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                            .add(populationCountText))
                                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .add(addJobButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 56, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                        .add(21, 21, 21))
                                    .add(manuallyGenerateLayout.createSequentialGroup()
                                        .add(deleteJobButton)
                                        .addContainerGap())))
                            .add(manuallyGenerateLayout.createSequentialGroup()
                                .add(jLabel13)
                                .addContainerGap())))
                    .add(manuallyGenerateLayout.createSequentialGroup()
                        .add(70, 70, 70)
                        .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, manuallyCancelButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, manuallyOkButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 75, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                        .addContainerGap())))
        );
        manuallyGenerateLayout.setVerticalGroup(
            manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(manuallyGenerateLayout.createSequentialGroup()
                .addContainerGap()
                .add(jScrollPane5, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
                .addContainerGap())
            .add(org.jdesktop.layout.GroupLayout.TRAILING, manuallyGenerateLayout.createSequentialGroup()
                .add(54, 54, 54)
                .add(manuallyOkButton)
                .add(19, 19, 19)
                .add(manuallyCancelButton)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 21, Short.MAX_VALUE)
                .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel16)
                    .add(populationCountText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .add(14, 14, 14)
                .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel11)
                    .add(jLabel12))
                .add(15, 15, 15)
                .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(durationText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(deadlineText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(addJobButton))
                .add(15, 15, 15)
                .add(jLabel13)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(manuallyGenerateLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(deleteNumberText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(deleteJobButton))
                .add(17, 17, 17))
        );
        showDialog.setModal(true);
        showDialog.setResizable(false);
        showDialog.setSize(450, 350);
        locateCenter(showDialog);
        jTable2.setModel(showIndModel);
        jScrollPane6.setViewportView(jTable2);

        jLabel14.setText("Fitness:");

        jLabel15.setText("Entire deadline:");

        jButton17.setText("Cancel");
        jButton17.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton17MouseClicked(evt);
            }
        });

        org.jdesktop.layout.GroupLayout showDialogLayout = new org.jdesktop.layout.GroupLayout(showDialog.getContentPane());
        showDialog.getContentPane().setLayout(showDialogLayout);
        showDialogLayout.setHorizontalGroup(
            showDialogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(showDialogLayout.createSequentialGroup()
                .addContainerGap()
                .add(jScrollPane6, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 213, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(showDialogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(showDialogLayout.createSequentialGroup()
                        .add(26, 26, 26)
                        .add(showDialogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                            .add(showDialogLayout.createSequentialGroup()
                                .add(jLabel14)
                                .add(20, 20, 20)
                                .add(fitnessText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 123, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                            .add(showDialogLayout.createSequentialGroup()
                                .add(jLabel15)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(entireDeadlineText))))
                    .add(showDialogLayout.createSequentialGroup()
                        .add(63, 63, 63)
                        .add(jButton17)))
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        showDialogLayout.setVerticalGroup(
            showDialogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(showDialogLayout.createSequentialGroup()
                .addContainerGap()
                .add(jScrollPane6, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 275, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(14, Short.MAX_VALUE))
            .add(org.jdesktop.layout.GroupLayout.TRAILING, showDialogLayout.createSequentialGroup()
                .add(52, 52, 52)
                .add(jButton17)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 90, Short.MAX_VALUE)
                .add(showDialogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel14)
                    .add(fitnessText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .add(19, 19, 19)
                .add(showDialogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(jLabel15)
                    .add(entireDeadlineText, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .add(78, 78, 78))
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Genetic Algorithm");
        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 366, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 295, Short.MAX_VALUE)
        );

        showCreatingBtn.setText("Create population");
        showCreatingBtn.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton1MouseClicked(evt);
            }
        });

        runButton.setText("Run");
        runButton.addMouseListener(new MouseAdapter(){
        	
        	public void mouseClicked(MouseEvent e) {
        		
        		disableButtonsDuringRun(true);
        		isStopped = false;
        		new Thread(alghorithmThread).start();
        		new Thread(statusThread).start();
        	}
        });
        stopButton.setText("Stop");
        stopButton.addMouseListener(new MouseAdapter(){
        	
        	public void mouseClicked(MouseEvent e) {

        		isStopped = true;
        		disableButtonsDuringRun(false);
        	}
        });

        jLabel1.setText("Individuals:");

        bestTextField.setText("Fitness");

        showIndBest.setText("Show");
        showIndBest.setMargin(new java.awt.Insets(2, 4, 2, 4));
        showIndBest.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
               
            	showIndividual(bestIndividual);
            	showDialog.setVisible(true);
            }
        });

        jLabel2.setText("Best");

        jLabel3.setText("Worst");

        worstTextField.setText("Fitness");

        showIndWorst.setText("Show");
        showIndWorst.setMargin(new java.awt.Insets(2, 4, 2, 4));
        showIndWorst.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
               
            	showIndividual(worstIndividual);
            	showDialog.setVisible(true);
            }
        });

        showSettingBtn.setText("Algorithm Setting");
        showSettingBtn.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton6MouseClicked(evt);
            }
        });

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(14, 14, 14)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(14, 14, 14)
                        .add(jSeparator1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 184, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(layout.createSequentialGroup()
                        .add(42, 42, 42)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                .add(2, 2, 2)
                                .add(showSettingBtn))
                            .add(org.jdesktop.layout.GroupLayout.LEADING, runButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, showCreatingBtn, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, stopButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .add(layout.createSequentialGroup()
                        .add(23, 23, 23)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jLabel2)
                            .add(jLabel3))
                        .add(9, 9, 9)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jLabel1)
                            .add(layout.createSequentialGroup()
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                                    .add(org.jdesktop.layout.GroupLayout.LEADING, worstTextField)
                                    .add(org.jdesktop.layout.GroupLayout.LEADING, bestTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 74, Short.MAX_VALUE))
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                                    .add(showIndWorst, 0, 0, Short.MAX_VALUE)
                                    .add(showIndBest, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(9, 9, 9)
                        .add(showCreatingBtn)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(runButton)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(stopButton)
                        .add(31, 31, 31)
                        .add(showSettingBtn)
                        .add(26, 26, 26)
                        .add(jSeparator1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 11, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 14, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(15, 15, 15)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(bestTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                            .add(jLabel2)
                            .add(showIndBest))
                        .add(18, 18, 18)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(jLabel3)
                            .add(worstTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                            .add(showIndWorst)))
                    .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(24, Short.MAX_VALUE))
        );
        
        messageDialog.getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        messageDialog.setModal(true);
        messageDialog.setResizable(false);
        messageDialog.setSize(400, 150);
        locateCenter(messageDialog);
        jLabel17.setText("The population has became homogeneous.");
        messageDialog.getContentPane().add(jLabel17, new org.netbeans.lib.awtextra.AbsoluteConstraints(90, 20, -1, -1));

        jButton18.setText("Cancel");
        jButton18.addMouseListener(new MouseAdapter(){
        	
        	public void mouseClicked(MouseEvent e) {
        		
        		messageDialog.setVisible(false);
        	}
        });
        messageDialog.getContentPane().add(jButton18, new org.netbeans.lib.awtextra.AbsoluteConstraints(170, 50, -1, -1));

        disableButtonsDuringRun(true);
        showCreatingBtn.setEnabled(true);
		stopButton.setEnabled(false);
		showSettingBtn.setEnabled(true);
        
        pack();
    }// </editor-fold>                        

    private void jButton11ActionPerformed(java.awt.event.ActionEvent evt) {                                          
// TODO add your handling code here:
    }                                         

    private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {                                          
// TODO add your handling code here:
    }                                         

                                  

    private void jButton8MouseClicked(java.awt.event.MouseEvent evt) {                                      
        settingDialog.setVisible(false);
    }                                     

    private void jButton17MouseClicked(java.awt.event.MouseEvent evt) {                                       

        showDialog.setVisible(false);
    }                                      

    

    private void jButton11MouseClicked(java.awt.event.MouseEvent evt) {                                       

        manuallyGenerate.setVisible(true);
    }                                      

    private void jButton10MouseClicked(java.awt.event.MouseEvent evt) {                                       

        autoGenerate.setVisible(true);
    }                                      

    private void jButton6MouseClicked(java.awt.event.MouseEvent evt) {                                      

        settingDialog.setVisible(true);
    }                                     

    private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {                                      
        
        creatingDialog.setVisible(true);
    }                                     
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }
    
    private void drawCircle(Ellipse2D rec, double fitness, Graphics2D g){
		
		Random random = new Random();
		if (rec.getHeight() == 0 && rec.getWidth() == 0) {
			int centerX = random.nextInt(DEFAULT_WIDTH - RADIUS * 2) + RADIUS;
			int centerY = random.nextInt(DEFAULT_HEIGHT - RADIUS * 2) + RADIUS;
			rec.setFrameFromCenter(centerX, centerY, centerX + RADIUS, centerY
					+ RADIUS);
		}
		Color color = Utils.generateColor(fitness);
		g.setPaint(color);
		g.setBackground(color);
		g.draw(rec);
		g.fill(rec);
	}
	
	private void drawCircles(Graphics2D g){
		
		List<Ellipse2D> elList = paintHolder.getElList();
		List<Individual> indList = paintHolder.getIndividuals();
		for(int i = 0; i < elList.size(); i++){
			
			drawCircle(elList.get(i), getFitness().calculate(indList.get(i)), g);
		}
	}
	
	public PairsHolder getPaintHolder() {
		return paintHolder;
	}
    
    public Fitness getFitness(){
    	
    	return fitness;
    }
    
    private Algorithm getAlgorithm(){
    	
    	return algorithm;
    }

	public Individual getBestIndividual() {
		return bestIndividual;
	}

	public void setBestIndividual(Individual bestIndividual) {
		this.bestIndividual = bestIndividual;
	}

	public Individual getWorstIndividual() {
		return worstIndividual;
	}

	public void setWorstIndividual(Individual worstIndividual) {
		this.worstIndividual = worstIndividual;
	}
	
	public void updateStatus(){
		
		if ((bestIndividual != null) && (worstIndividual != null)){
			
			NumberFormat format = NumberFormat.getNumberInstance();
			double bestRes = getFitness().calculate(bestIndividual);
			double worstRes = getFitness().calculate(worstIndividual);
			bestTextField.setText(format.format(bestRes));
			worstTextField.setText(format.format(worstRes));
			if (Double.compare(bestRes, worstRes) == 0){
				
				isStopped = true;
				disableButtonsDuringRun(false);
				messageDialog.setVisible(true);
			}
			
		}
	}
	
	private void locateCenter(Component component){
		
		component.setLocation(screenSize.width / 2 - component.getWidth() / 2,
				screenSize.height / 2 - component.getHeight() / 2);
	}
	
	private void disableButtonsDuringRun(boolean disable){
		
		showCreatingBtn.setEnabled(!disable);
		stopButton.setEnabled(disable);
		runButton.setEnabled(!disable);
		showIndBest.setEnabled(!disable);
		showIndWorst.setEnabled(!disable);
		showSettingBtn.setEnabled(!disable);
	}
	
	private void showIndividual(Individual individual){
		
		for (int i = showIndModel.getRowCount() - 1; i >=0; i--){
			
			showIndModel.removeRow(i);
		}
		for (Job job : individual.getJobs()){
			
			showIndModel.addRow(new Object []{job.getNumber(), job.getDuration(), job.getDeadline()});
		}
		double fitness = getFitness().calculate(individual);
		fitnessText.setText(NumberFormat.getNumberInstance().format(fitness));
		entireDeadlineText.setText(((int)Math.round(1/fitness)) + "");
	}
	
	private static String[] getNames(List<Method> methods){
		
		List<String> result = new ArrayList<String>();
		for(Method method : methods){
			
			result.add(method.getName());
		}
		return result.toArray(new String[0]);
	}
}
